package com.mine.modules.vm.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.mine.common.config.exception.MineBootException;
import com.mine.common.domain.vo.Result;
import com.mine.common.utils.AnnotationUtil;
import com.mine.common.utils.DateUtils;
import com.mine.modules.sys.entity.SysDict;
import com.mine.modules.sys.entity.SysDictItem;
import com.mine.modules.sys.service.ISysDictItemService;
import com.mine.modules.vm.common.constant.BizConstant;
import com.mine.modules.vm.common.utils.SensorUtil;
import com.mine.modules.vm.domain.dto.BatchAddElementDto;
import com.mine.modules.vm.domain.dto.BatchAddSensorGroupDto;
import com.mine.modules.vm.domain.dto.QueryElementDto;
import com.mine.modules.vm.domain.query.SensorQuery;
import com.mine.modules.vm.domain.vo.SensorValue;
import com.mine.modules.vm.entity.*;
import com.mine.modules.vm.mapper.VmSensorMapper;
import com.mine.modules.vm.service.IVmSensorElementService;
import com.mine.modules.vm.service.IVmSensorService;
import com.mine.modules.vm.service.IVmSensorTreeService;
import lombok.RequiredArgsConstructor;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 传感器 服务实现类
 * </p>
 *
 * @author xujf
 * @since 2024-11-08
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VmSensorServiceImpl extends ServiceImpl<VmSensorMapper, VmSensor> implements IVmSensorService {

    private final IVmSensorTreeService vmSensorTreeService;

    private final IVmSensorElementService vmSensorElementService;

    private final ISysDictItemService sysDictItemService;

    private final SensorUtil sensorUtil;

    @Override
    public Result<?> queryPageList(SensorQuery sensorQuery) {
        LambdaQueryWrapper<VmSensor> queryWrapper = new LambdaQueryWrapper<>(VmSensor.class);
        queryWrapper.and(
                StringUtils.isNotBlank(sensorQuery.getKeywords()),
                e -> e.like(VmSensor::getCode, sensorQuery.getKeywords())
                        .or()
                        .like(VmSensor::getName, sensorQuery.getKeywords())
        );
        if (StringUtils.isNotBlank(sensorQuery.getDeviceId())) {
            List<String> ids = this.vmSensorElementService.lambdaQuery()
                    .eq(VmSensorElement::getElementId, sensorQuery.getDeviceId())
                    .list().stream().map(VmSensorElement::getSensorId).collect(Collectors.toList());
            if (ids.isEmpty()) {
                return Result.ok(Collections.emptyList());
            }
            queryWrapper.in(VmSensor::getId, ids);
        }
        queryWrapper.eq(StringUtils.isNotBlank(sensorQuery.getTreeId()), VmSensor::getTreeId, sensorQuery.getTreeId());
        Page<VmSensor> page = new Page<>(sensorQuery.getPageNo(), sensorQuery.getPageSize());
        IPage<VmSensor> pageList = this.page(page, queryWrapper);
        return Result.OK("查询成功！", pageList);
    }

    @Override
    public Result<?> queryPageListNotInDevice(SensorQuery sensorQuery) {
        LambdaQueryWrapper<VmSensor> queryWrapper = new LambdaQueryWrapper<>(VmSensor.class);
        queryWrapper.and(
                StringUtils.isNotBlank(sensorQuery.getKeywords()),
                e -> e.like(VmSensor::getCode, sensorQuery.getKeywords())
                        .or()
                        .like(VmSensor::getName, sensorQuery.getKeywords())
        );
        if (StringUtils.isNotBlank(sensorQuery.getDeviceId())) {
            List<String> ids = this.vmSensorElementService.lambdaQuery()
                    .eq(VmSensorElement::getElementId, sensorQuery.getDeviceId())
                    .list().stream().map(VmSensorElement::getSensorId).collect(Collectors.toList());
            queryWrapper.notIn(!ids.isEmpty(), VmSensor::getId, ids);
        }
        queryWrapper.eq(StringUtils.isNotBlank(sensorQuery.getTreeId()), VmSensor::getTreeId, sensorQuery.getTreeId());
        Page<VmSensor> page = new Page<>(sensorQuery.getPageNo(), sensorQuery.getPageSize());
        IPage<VmSensor> pageList = this.page(page, queryWrapper);
        return Result.OK("查询成功！", pageList);
    }

    @Override
    public Result<?> batchAddSensorGroup(BatchAddSensorGroupDto addSensorGroups) {
        if (StringUtils.isEmpty(addSensorGroups.getGroupCode()) || StringUtils.isEmpty(addSensorGroups.getSensorCodes())) {
            return Result.error("参数不完整!");
        }
        SysDictItem item = sysDictItemService.lambdaQuery().eq(SysDictItem::getItemValue, addSensorGroups.getGroupCode()).one();
        if (item == null) {
            return Result.error("分组不存在！");
        }
        this.lambdaQuery()
                .in(VmSensor::getCode, Arrays.asList(addSensorGroups.getSensorCodes().split(",")))
                .list()
                .forEach(e -> {
                    e.setGroupId(addSensorGroups.getGroupCode());
                    this.updateById(e);
                });
        return Result.ok("操作成功！");
    }

    @Override
    public Result<?> sensorGroupListByLayerId(String layerId) {
        //图层下设备id集合
        List<String> ids = Db.lambdaQuery(VmLayerElement.class)
                .in(VmLayerElement::getLayerId, layerId)
                .eq(VmLayerElement::getElementType, BizConstant.SCENE_ELEMENT_TYPE_ASSET)
                .list().stream().map(VmLayerElement::getElementId).collect(Collectors.toList());

        //设备下传感器id集合
        List<String> sensorIds = Db.lambdaQuery(VmSensorElement.class)
                .in(VmSensorElement::getElementId, ids)
                .list()
                .stream()
                .map(VmSensorElement::getSensorId)
                .collect(Collectors.toList());

        SysDict dict = Db.lambdaQuery(SysDict.class).eq(SysDict::getDictCode, BizConstant.SENSOR_GROUP_DICT_CODE).one();
        if (dict == null) {
            return Result.error("未找到显示分组数据字典配置！");
        }
        List<Map<String, Object>> res = new ArrayList<>();
        Db.lambdaQuery(SysDictItem.class).eq(SysDictItem::getDictId, dict.getId()).list().forEach(e -> {
            List<VmSensor> rows = this.lambdaQuery()
                    .in(VmSensor::getId, sensorIds)
                    .eq(VmSensor::getGroupId, e.getItemValue())
                    .list();
            if (!rows.isEmpty()) {
                Map<String, Object> map = new HashMap<>();
                map.put("group", rows);
                res.add(map);
            }
        });
        return Result.OK(res);
    }

    @Override
    public Result<?> editSensorAliasById(String id, String alias) {
        if(StringUtils.isBlank(alias)){
            return Result.error("参数必填！");
        }
        VmSensor vmSensor = this.getById(id);
        if(vmSensor == null){
            return Result.error("数据不存在，请刷新重试！");
        }
        vmSensor.setAlias(alias);
        if(this.updateById(vmSensor)){
            return Result.ok("修改成功！");
        }else{
            return Result.error("修改失败！");
        }
    }

    @Override
    public Result<?> editSensorAliasByCode(String code, String alias) {
        if(StringUtils.isBlank(alias)){
            return Result.error("参数必填！");
        }
        VmSensor vmSensor = this.lambdaQuery().eq(VmSensor::getCode, code).one();
        if(vmSensor == null){
            return Result.error("数据不存在，请刷新重试！");
        }
        vmSensor.setAlias(alias);
        if(this.updateById(vmSensor)){
            return Result.ok("修改成功！");
        }else{
            return Result.error("修改失败！");
        }
    }

    @Override
    public Result<?> getDataValue(String tableName, String startTime, String endTime) {
        if (StringUtils.isBlank(tableName)) {
            return Result.error("参数必填！");
        }
        String[] points = tableName.split(",");
        List<Object> res = new ArrayList<>();
        for (String point : points) {
            Map<String, Object> obj = new HashMap<>();
            List<SensorValue> dataList = new ArrayList<>();
            JSONArray dataValue = sensorUtil.queryAggregation(point, startTime, endTime);
            if (dataValue != null && !dataValue.isEmpty()) {
                for (Object o : dataValue) {
                    JSONObject data = (JSONObject) o;
                    dataList.add(new SensorValue(data.getLong("ts"), data.getString("dataValue")));
                }
            }
            obj.put("point", point);
            obj.put("data", dataList);
            res.add(obj);
        }
        return Result.ok(res);
    }

    @Override
    public Result<?> pageDataValue(Integer pageNo, Integer pageSize, String tableName, String startTime, String endTime) {
        if (StringUtils.isBlank(tableName)) {
            return Result.error("参数必填！");
        }
        return Result.ok(sensorUtil.valueDataQuery(tableName, startTime, endTime, String.valueOf(pageNo), String.valueOf(pageSize)));
    }

    @Override
    public Result<?> sensorQueryTime(String tableName, String dateTime) {
        if (StringUtils.isBlank(tableName)) {
            return Result.error("参数必填！");
        }
        String[] points = tableName.split(",");
        List<Object> res = new ArrayList<>();
        for (String point : points) {
            Map<String, Object> obj = new HashMap<>();
            List<SensorValue> dataList = new ArrayList<>();
            JSONArray dataValue = sensorUtil.queryTime(point, dateTime);
            if (dataValue != null && !dataValue.isEmpty()) {
                for (Object o : dataValue) {
                    JSONObject data = (JSONObject) o;
                    dataList.add(new SensorValue(data.getLong("ts"), data.getString("dataValue")));
                }
            }
            obj.put("point", point);
            obj.put("data", dataList);
            res.add(obj);
        }
        return Result.ok(res);
    }

    @Override
    @Synchronized
    @Transactional(rollbackFor = Exception.class)
    public void synSensors() {
        try {
            log.info("************开始同步数采平台数据***********");
            long start = System.currentTimeMillis();
            JSONArray list = sensorUtil.getAllPoint();
            if (list != null && !list.isEmpty()) {
                List<String> das = new ArrayList<>();
                List<String> poitsIds = new ArrayList<>();
                for (Object object : list) {
                    JSONObject row = (JSONObject) object;
                    String tree_id = row.getString("id");
                    String tree_name = row.getString("tree_name");
                    String tree_code = row.getString("tree_code");
                    String dangerous_code = row.getString("dangerous_code");
                    JSONArray points = row.getJSONArray("points");
                    if (StringUtils.isNotBlank(tree_name) && StringUtils.isNotBlank(tree_code)) {
                        das.add(tree_id);
                        //2.查询分类是否存在
                        VmSensorTree sensorTree = vmSensorTreeService.getById(tree_id);
                        if (sensorTree == null) {
                            sensorTree = new VmSensorTree();
                            sensorTree.setId(row.getString("id"));
                            sensorTree.setTreeCode(tree_code);
                            vmSensorTreeService.save(sensorTree);
                        }
                        if (!StringUtils.equals("01", tree_code)) {
                            sensorTree.setParentId(row.getString("parent_id"));
                        }
                        sensorTree.setTreeName(tree_name);
                        sensorTree.setDangerousCode(dangerous_code);
                        sensorTree.setSort(row.getInteger("sort"));
                        sensorTree.setSrcId(row.getString("id"));
                        if (vmSensorTreeService.updateById(sensorTree)) {
                            if (points != null && !points.isEmpty()) {
                                for (Object point : points) {
                                    JSONObject ret = (JSONObject) point;
                                    String item_des = ret.getString("item_des");
                                    String item_unit = ret.getString("item_unit");
                                    String value_type = ret.getString("value_type");
                                    String table_name = ret.getString("table_name");
                                    if (StringUtils.isNotBlank(table_name) && StringUtils.isNotBlank(item_des)) {
                                        poitsIds.add(table_name);
                                        VmSensor sensor = lambdaQuery().eq(VmSensor::getCode, table_name).one();
                                        if (sensor == null) {
                                            sensor = new VmSensor();
                                            sensor.setCode(table_name);
                                            sensor.setName(item_des);
                                            sensor.setAlias(item_des);
                                            this.save(sensor);
                                        }
                                        sensor.setName(item_des);
                                        sensor.setTreeId(sensorTree.getId());
                                        sensor.setTreeCode(tree_code);
                                        sensor.setUnit(item_unit);
                                        sensor.setValueType(value_type);
                                        sensor.setBlueLower(ret.getString("blue_lower"));
                                        sensor.setBlueUpper(ret.getString("blue_upper"));
                                        sensor.setOrangeLower(ret.getString("orange_lower"));
                                        sensor.setOrangeUpper(ret.getString("orange_upper"));
                                        sensor.setYellowLower(ret.getString("yellow_lower"));
                                        sensor.setYellowUpper(ret.getString("yellow_upper"));
                                        sensor.setRedUpper(ret.getString("red_upper"));
                                        sensor.setRedLower(ret.getString("red_lower"));
                                        sensor.setSrcId(ret.getString("id"));
                                        this.updateById(sensor);
                                    }
                                }
                            }
                        }
                    }
                }
                ////*************删除本数据*******************////
                if (!poitsIds.isEmpty()) {
                    this.lambdaUpdate().notIn(VmSensor::getCode, poitsIds).remove();
                }
                if (!das.isEmpty()) {
                    this.vmSensorTreeService.lambdaUpdate().notIn(VmSensorTree::getId, das).remove();
                }
                log.info("设备及传感器同步成功！耗时：【{}】毫秒", System.currentTimeMillis() - start);
            } else {
                log.error("设备信息及传感器信息接口无数据返回");
            }
        } catch (Exception e) {
            log.error("设备信息及传感器同步异常【{}】！", e.getMessage());
            throw new MineBootException("设备信息及传感器同步异常【" + e.getMessage() + "】！");
        }

    }
}
